/**
 * KopsoxApplicationServices
 * Copyright (C) 2010 Free Software Foundation, Inc. <http://fsf.org/>
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.kopsox.services.message;

import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Very simple messaging service with integrated filter possiblities.
 * NOTE: Message will not be stored! Each message is sent in an new thread
 * 
 * @author Konrad Renner
 *
 */
public final class SimpleMessageService {
	
	private final static SimpleMessageService INSTANCE = new SimpleMessageService();

	private final Map<String, MessageConsumer> consumerMap;
	
	private SimpleMessageService() {
		this.consumerMap = new ConcurrentHashMap<String, MessageConsumer>();
	}
	
	/**
	 * Registers a new consumer to the service. Returns true if the consumer was registered
	 * 
	 * @param name
	 * @param consumer
	 * @return boolean
	 * @author Konrad Renner
	 */
	public static final boolean registerConsumer(String name,MessageConsumer consumer) {
		if(INSTANCE.consumerMap.containsKey(name)) {
			return false;
		}
		
		INSTANCE.consumerMap.put(name, consumer);
		
		return true;
	}
	
	/**
	 * Unregisters a new consumer to the service. Returns true if the consumer was unregistered
	 * 
	 * @param name
	 * @return boolean
	 * @author Konrad Renner
	 */
	public static final boolean unregisterConsumer(String name) {
		if(INSTANCE.consumerMap.containsKey(name)) {
			INSTANCE.consumerMap.remove(name);
			return true;
		}
		
		return false;
	}
	
	/**
	 * Sends a message to all registered Consumers
	 * 
	 * @param message
	 * @author Konrad Renner
	 */
	public static final void sendMessageToAllConsumers(SimpleMessage message) {
		Collection<MessageConsumer> consumrs = INSTANCE.consumerMap.values();
		
		for(MessageConsumer consumer : consumrs) {
			if(consumer.isMessageServiceable(message)) {
				Thread sender = new Thread(new SendingThread(consumer, message));
				sender.start();
			}
		}
	}
	
	/**
	 * Sends a message to the consumer with the given name. Returns true if the message was sent
	 * 
	 * @param consumerName
	 * @param message
	 * @return boolean
	 * @author Konrad Renner
	 */
	public static final boolean sendMessageToConsumer(String consumerName,SimpleMessage message) {
		if(INSTANCE.consumerMap.containsKey(consumerName)) {
			Thread sender = new Thread(new SendingThread(INSTANCE.consumerMap.get(consumerName), message));
			sender.start();
			
			return true;
		}
		
		return false;
	}
	
	private final static class SendingThread implements Runnable{
		
		private final MessageConsumer consumer;
		private final SimpleMessage message;
		
		public SendingThread(MessageConsumer consumer,SimpleMessage message) {
			this.consumer = consumer;
			this.message = message;
		}

		@Override
		public void run() {
			this.consumer.retrieveMessage(this.message);
		}
	}
}
